package com.hn658.groupshare.filemgmt.service.impl;

import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.Map;

import javax.annotation.Resource;
import javax.imageio.ImageIO;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.ChecksumException;
import com.google.zxing.EncodeHintType;
import com.google.zxing.FormatException;
import com.google.zxing.LuminanceSource;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.NotFoundException;
import com.google.zxing.Result;
import com.google.zxing.WriterException;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.qrcode.QRCodeReader;
import com.hn658.framework.common.AbstractBusinessObject;
import com.hn658.framework.file.media.image.IImageManager;
import com.hn658.framework.file.media.image.ThumbGeneratorMode;
import com.hn658.framework.logging.enums.LogCategory;
import com.hn658.framework.shared.utils.UUIDUtils;
import com.hn658.groupshare.common.utils.HSLColor;
import com.hn658.groupshare.config.service.IGroupShareConfig;
import com.hn658.groupshare.filemgmt.service.IFileManager;
import com.hn658.groupshare.filemgmt.service.IValidator;
import com.hn658.groupshare.filemgmt.service.exception.FileException;

/**
 * 
 * <p>
 * 描述：
 * </p>
 * <p>
 * </p>
 * 
 * @ClassName: FileManagerImpl
 * @date 2014年9月1日 下午3:12:23
 */
@Component("fileManagerImpl")
public class FileManagerImpl extends AbstractBusinessObject implements IFileManager {

	@Resource(name = "jMagickImageManager")
	private IImageManager imageMger;

	@Autowired
	private IGroupShareConfig config;

	@Override
	public String[] saveAvatarImage(byte[] image) {
		String imageRootDir = config.getImageRootDir();
		String imageSizeList = config.getImageSizeList();
		imageRootDir = FilenameUtils.normalize(imageRootDir);
		// 原始图片全路径
		String imageFullUrl = FilenameUtils.normalize(imageRootDir + System.getProperty("file.separator")
				+ UUIDUtils.getUUID() + System.getProperty("file.separator") + "avatar.jpg");
		// 生成路径(包含原图片路径及缩略图路径)
		String[] geneUrlArray = new String[imageSizeList.split("[,;]").length + 1];
		// 赋值原图片路径
		int index = imageFullUrl.lastIndexOf(
				System.getProperty("file.separator") + "groupshare" + System.getProperty("file.separator"));
		if (index != -1) {
			geneUrlArray[0] = imageFullUrl.substring(index);// 原始图片路径
		}

		logger.debug(LogCategory.SYSTEM, "生成完整的文件名:{}", imageFullUrl);

		OutputStream outputStream = null;
		try {
			File imagePreFix = new File(FilenameUtils.getFullPathNoEndSeparator(imageFullUrl));
			FileUtils.forceMkdir(imagePreFix);// 生成目录如果文件目录不存在

			outputStream = new FileOutputStream(new File(imageFullUrl));
			outputStream.write(image);
			outputStream.close();

			// 生成缩略图，多个缩略图路径之间用","分割
			imageMger.generateThumb(imageFullUrl, ThumbGeneratorMode.ScaleByWidthAndHeight, imageRootDir, imageSizeList);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
			logger.debug(LogCategory.SYSTEM, "文件{}没有找到{}", new Object[] { imageFullUrl, e });
			throw new FileException(FileException.UploadFileIsEmpty, e);
		} catch (IOException e) {
			e.printStackTrace();
			logger.debug(LogCategory.SYSTEM, "生成文件{}出错{}", e);

			throw new FileException(FileException.IOException, e);
		}
		return geneUrlArray;
	}

	@Override
	public String[] saveQrCodeImage(byte[] image, IValidator validator) {
		String imageRootDir = config.getImageRootDir();
		String imageSizeList = config.getImageSizeList();
		imageRootDir = FilenameUtils.normalize(imageRootDir);
		// 原始图片全路径
		String imageFullUrl = FilenameUtils.normalize(imageRootDir + System.getProperty("file.separator")
				+ UUIDUtils.getUUID() + System.getProperty("file.separator") + "qrcode.jpg");
		// 生成路径(包含原图片路径及缩略图路径)
		String[] geneUrlArray = new String[imageSizeList.split("[,;]").length + 1];
		// 赋值原图片路径
		int index = imageFullUrl.lastIndexOf(
				System.getProperty("file.separator") + "groupshare" + System.getProperty("file.separator"));
		if (index != -1) {
			geneUrlArray[0] = imageFullUrl.substring(index);// 原始图片路径
		}

		logger.debug(LogCategory.SYSTEM, "生成完整的文件名:{}", imageFullUrl);

		OutputStream outputStream = null;
		try {
			File imagePreFix = new File(FilenameUtils.getFullPathNoEndSeparator(imageFullUrl));
			FileUtils.forceMkdir(imagePreFix);// 生成目录如果文件目录不存在

			outputStream = new FileOutputStream(new File(imageFullUrl));
			outputStream.write(image);
			outputStream.close();

			// 扫描二维码
			String qrcodeText = qrCode(image, imageFullUrl);
			
			if(validator != null){
				validator.validateQrcode(qrcodeText);
			}
			
			geneUrlArray[1] = qrcodeText ;

			// 生成缩略图，多个缩略图路径之间用","分割
			imageMger.generateThumb(imageFullUrl, ThumbGeneratorMode.ScaleByWidthAndHeight,imageRootDir, imageSizeList);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
			logger.debug(LogCategory.SYSTEM, "文件{}没有找到{}", new Object[] { imageFullUrl, e });

			throw new FileException(FileException.UploadFileIsEmpty, e);
		} catch (IOException e) {
			e.printStackTrace();
			logger.debug(LogCategory.SYSTEM, "生成文件{}出错{}", new Object[] { imageFullUrl, e });

			throw new FileException(FileException.IOException, e);
		} catch (WriterException e) {
			e.printStackTrace();
			logger.debug(LogCategory.SYSTEM, "生成文件{}出错{}", new Object[] { imageFullUrl, e });

			throw new FileException(FileException.WriterException, e);
		} catch (NotFoundException e) {
			e.printStackTrace();
			logger.debug(LogCategory.SYSTEM, "无法解析二维码{}出错{}", new Object[] { imageFullUrl, e });

			throw new FileException(FileException.NotFoundException, e);
		} catch (ChecksumException e) {
			e.printStackTrace();
			logger.debug(LogCategory.SYSTEM, "扫描二维码{}出错{}", new Object[] { imageFullUrl, e });

			throw new FileException(FileException.ChecksumException, e);

		} catch (FormatException e) {
			e.printStackTrace();
			logger.debug(LogCategory.SYSTEM, "扫描二维码{}出错{}", new Object[] { imageFullUrl, e });

			throw new FileException(FileException.FormatException, e);

		}

		return geneUrlArray;
	}

	private String qrCode(byte[] imageSource, String fileurl)
			throws WriterException, IOException, NotFoundException, ChecksumException, FormatException {

		BufferedImage image = ImageIO.read(new ByteArrayInputStream(imageSource));
		image = grayImage(image);
		LuminanceSource source = new BufferedImageLuminanceSource(image);
		BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));

		Result result = new QRCodeReader().decode(bitmap);
		Map<EncodeHintType, Object> hints = new HashMap<EncodeHintType, Object>();
		hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
		BitMatrix bitMatrix = new MultiFormatWriter().encode(result.getText(), BarcodeFormat.QR_CODE, 800, 800, hints);// 生成矩阵
		Path path = FileSystems.getDefault().getPath(fileurl);
		MatrixToImageWriter.writeToPath(bitMatrix, "jpg", path);// 输出图像
		
		return result.getText();
	}

	public static BufferedImage grayImage(final BufferedImage srcImg) {
		int width = srcImg.getWidth();
		int height = srcImg.getHeight();
		int[] pixels = new int[width * height];
		srcImg.getRGB(0, 0, width, height, pixels, 0, width);
		int newPixels[] = new int[width * height];
		for (int i = 0; i < width * height; i++) {
			HSLColor hslColor = new HSLColor(HSLColor.fromRGB(new Color(pixels[i])));
			newPixels[i] = hslColor.adjustSaturation(0).getRGB();
		}
		BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
		bi.setRGB(0, 0, width, height, newPixels, 0, width);
		return bi;
	}

}
